import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
import { Result } from '#/api.ts';
import { ResultEnum, ResultMessage } from '#/enmu.ts';
import UserStore from '@/store/userStore.ts';
import { message as Message } from 'antd';

// 创建 axios 实例
const axiosInstance = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 50000,
  headers: { 'Content-Type': 'application/json;charset=utf-8' },
});

// 请求拦截
axiosInstance.interceptors.request.use(
  (config) => {
    const { token } = UserStore.getState().userInfo;
    if (token) {
      config.headers.token = token;
    }
    return config;
  },
  (error) => {
    // TODO: 请求错误时做些什么
    return Promise.reject(error);
  },
);

// 响应拦截
axiosInstance.interceptors.response.use(
  (res: AxiosResponse) => {
    //TODO: 根据实际情况处理错误
    if (!res.data) throw new Error(ResultMessage.ApiRequestFailed);

    const { code, data, message } = res.data;

    // 业务请求成功
    const hasSuccess = data && Reflect.has(res.data, 'code') && code === ResultEnum.SUCCESS;
    if (hasSuccess) {
      return res.data;
    }

    if (data.errCode === 20005 || data.errCode === 20007) {
      Message.error({ content: data.errMsg, duration: 1 }).then(() => {
        UserStore.setState({ userInfo: {} });
        location.href = '/login';
      });
    }

    // 业务请求错误
    throw new Error(data.errMsg || message || ResultMessage.ApiRequestFailed);
  },
  (error: AxiosError<Result>) => {
    //TODO: 根据实际情况处理错误
    const { response, message } = error;
    const errMsg = response?.data?.message || message || ResultMessage.ErrorMessage;
    Message.error(errMsg);

    return Promise.reject(error);
  },
);

class APIClient {
  get<T>(config: AxiosRequestConfig): Promise<Result<T>> {
    return this.request({ ...config, method: 'GET' });
  }

  post<T>(config: AxiosRequestConfig): Promise<Result<T>> {
    return this.request({ ...config, method: 'POST' });
  }

  put<T>(config: AxiosRequestConfig): Promise<Result<T>> {
    return this.request({ ...config, method: 'PUT' });
  }

  delete<T>(config: AxiosRequestConfig): Promise<Result<T>> {
    return this.request({ ...config, method: 'DELETE' });
  }

  getCancelToken() {
    return axios.CancelToken.source();
  }

  request<T>(config: AxiosRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      axiosInstance
        .request<unknown, AxiosResponse<Result>>(config)
        .then((res: AxiosResponse<Result>) => {
          resolve(res as unknown as Promise<T>);
        })
        .catch((e: Error | AxiosError) => {
          reject(e);
        });
    });
  }
}

export default new APIClient();
